package cn.net.mugui.net.task;

import java.net.DatagramSocket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

import com.mugui.base.base.Autowired;
import com.mugui.base.base.Component;
import com.mugui.base.client.net.auto.AutoTask;
import com.mugui.base.client.net.base.Task;
import com.mugui.base.client.net.base.TaskInterface;
import com.mugui.base.util.Other;

import cn.net.mugui.net.key.utils.Base58;
import cn.net.mugui.net.p2p.Server;
import cn.net.mugui.net.p2p.ServerAttr;
import cn.net.mugui.net.p2p.ServerManager;
import cn.net.mugui.net.udp.UdpBag;
import cn.net.mugui.net.udp.UdpServer;
import cn.net.mugui.net.udp.UdpServer.ReceiveListener;
import cn.net.mugui.net.udp.UdpServerManager;

/**
 * 保持连接处理器
 *
 * @author 木鬼
 */
@Component
@Task()
@AutoTask
public class KeepConnectionTask implements TaskInterface {

	@Autowired
	private Server server;
	@Autowired
	private ServerManager serverManager;
	@Autowired
	private UdpServerManager udpServerManager;
	private final HashMap<String, Long> map = new HashMap<>();
	private final HashMap<String, Long> now_map = new HashMap<>();
	ReceiveListener receiveListener = new ReceiveListener() {
		@Override
		public boolean ping(DatagramSocket socket, UdpServer server, UdpBag resolve) {
			// TODO Auto-generated method stub
			return false;
		}

		@Override
		public boolean retPing(DatagramSocket socket, UdpServer server, UdpBag resolve) {
			if (server != null) {
				String address = Base58.encode(resolve.getFrom());
				synchronized (map) {
					Long time = map.get(address);
					if (time != null) {
						map.put(address, System.currentTimeMillis());
						ServerAttr serverAttr = serverManager.get(address);
						serverAttr.setStatus(ServerAttr.status_3);
						serverAttr.setPing(System.currentTimeMillis()-time  );
						now_map.put(address, System.currentTimeMillis());
						System.out.println("重置：" + address + " :" + System.currentTimeMillis());
					}
				}
			}
			return true;
		}

		@Override
		public boolean sucess(DatagramSocket socket, UdpServer server, UdpBag resolve) {
			return false;
		}

	};

	public void init() {
		System.out.println(KeepConnectionTask.class.getName() + "初始化");
	}

	@Override
	public void run() {
		while (true) {
			try {
				handle();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	@Autowired
	private WaitConnectionTask waitConnectionTask;

	private void handle() {
		long time = System.currentTimeMillis();
		synchronized (map) {
			Iterator<Entry<String, Long>> iterator = map.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<String, Long> next = iterator.next();
				Long now_time = now_map.get(next.getKey());
				if(now_time==null) {
					now_map.put(next.getKey(), now_time=System.currentTimeMillis());
				}
				ServerAttr serverAttr = serverManager.get(next.getKey());
				if (serverAttr == null) {
					now_map.remove(next.getKey());
					iterator.remove();
					continue;
				}

				Long value = next.getValue();
				if(value==null) {
					next.setValue(value=System.currentTimeMillis());
				}
				System.out.println("重置：" + serverAttr.getAddress() + " :" + now_time + " " + value);
				if (value - now_time > 15000) {
					iterator.remove();
					serverAttr.setStatus(ServerAttr.status_0);
					// 重新链接
					waitConnectionTask.add(serverAttr.getAddress());
					continue;
				}
				UdpServer udpServer = udpServerManager.get(serverAttr.getAddress(), serverAttr.getHost(),
						serverAttr.getPort());
				try {
					server.ping(udpServer, serverAttr);
					next.setValue(System.currentTimeMillis());
				} catch (Exception e) {
					e.printStackTrace();
					serverAttr.setStatus(ServerAttr.status_0);
				}
			}
		}
		time = time + 3000 - System.currentTimeMillis();
		if (time <= 0) {
			time = 10;
		}
		Other.sleep((int) time);
	}
	
	

	@Autowired
	private PerHandleTask perHandleTask;
	public void add(String key) {
		synchronized (map) {
			perHandleTask.add(key);
			Long bs = map.get(key);
			if (bs == null) {
				bs = System.currentTimeMillis();
				now_map.put(key, bs);
				map.put(key, bs);
				ServerAttr serverAttr = serverManager.get(key);
				UdpServer udpServer = udpServerManager.get(serverAttr.getAddress(), serverAttr.getHost(),
						serverAttr.getPort());
				udpServer.setReceiveListener(receiveListener);
			}else {
				bs = System.currentTimeMillis();
				map.put(key, bs);
				now_map.put(key, bs);
			}
			map.notifyAll();
		}
	}

}
